#ifndef COMMON_TIMESPAN_H_
#define COMMON_TIMESPAN_H_
#include <fermat/common/timestamp.h>


namespace fermat {
/*!
* A class that represents time spans up to microsecond resolution.
*/
class  Timespan {
public:
	typedef Timestamp::TimeDiff TimeDiff;
	/*!
	*Creates a  zero Timespan.
	*/
	Timespan();
	
	/*!
	*Creates a Timespan with given time.
	*/
	Timespan(TimeDiff microseconds);
	
	/*!
	*Creates a Timespan with given time.
	*/
	Timespan(long seconds, long microseconds);
	
	/*!
	*Creates a Timespan with given time
	*/
	Timespan(int days, int hours, int minutes, int seconds, int microSeconds);
	

	/*!
	*Creates a Timespan with given another one.
	*/
	Timespan(const Timespan& timespan);
	/*!
	*Destroys the Timespan.
	*/
	~Timespan();
	
	/*!
	* Assignment operator.
	*/
	Timespan& operator = (const Timespan& timespan);
	
	/*!
	* Assignment operator.
	*/
	Timespan& operator = (TimeDiff microseconds);
	
	/*!
	* Assigns a new span.
	*/
	Timespan& assign(int days, int hours, int minutes, int seconds, int microSeconds);
	
	/*!
	* Assigns a new span.
	*/	
	Timespan& assign(long seconds, long microseconds);
	
	/*!
	* Swaps the Timespan with another one.
	*/	
	void swap(Timespan& timespan);

	bool operator == (const Timespan& ts) const;
	bool operator != (const Timespan& ts) const;
	bool operator >  (const Timespan& ts) const;
	bool operator >= (const Timespan& ts) const;
	bool operator <  (const Timespan& ts) const;
	bool operator <= (const Timespan& ts) const;

	bool operator == (TimeDiff microSeconds) const;
	bool operator != (TimeDiff microSeconds) const;
	bool operator >  (TimeDiff microSeconds) const;
	bool operator >= (TimeDiff microSeconds) const;
	bool operator <  (TimeDiff microSeconds) const;
	bool operator <= (TimeDiff microSeconds) const;
	
	Timespan operator + (const Timespan& d) const;
	Timespan operator - (const Timespan& d) const;
	Timespan& operator += (const Timespan& d);
	Timespan& operator -= (const Timespan& d);

	Timespan operator + (TimeDiff microSeconds) const;
	Timespan operator - (TimeDiff microSeconds) const;
	Timespan& operator += (TimeDiff microSeconds);
	Timespan& operator -= (TimeDiff microSeconds);

	/*!
	*@return the number of days.
	*/	
	int days() const;
	
	/*!
	*@return the number of hours (0 to 23).
	*/	
	int hours() const;
	
	/*!
	*@return the total number of hours.
	*/		
	int totalHours() const;

	/*!
	*@return the number of minutes (0 to 59).
	*/			
	int minutes() const;
	
	/*!
	*@return the total number of minutes.
	*/		
	int totalMinutes() const;
	
	/*!
	*@return the number of seconds (0 to 59).
	*/		
	int seconds() const;
	
	/*!
	*@return the total number of seconds.
	*/	
	int totalSeconds() const;
	
	/*!
	*@return the number of milliseconds (0 to 999).
	*/	
	int milliseconds() const;
	
	/*!
	*@return the total number of milliseconds.
	*/		
	TimeDiff totalMilliseconds() const;
	
	/*!
	*@return the fractions of a millisecond in microseconds (0 to 999).
	*/		
	int microseconds() const;

	/*!
	*@return  the fractions of a second in microseconds (0 to 999999).
	*/	
	int useconds() const;

	/*!
	*@return  the total number of microseconds.
	*/		
	TimeDiff totalMicroseconds() const;

	static const TimeDiff kMILLISECONDS; //!< The number of microseconds in a millisecond.
	static const TimeDiff kSECONDS;      //!< The number of microseconds in a second.
	static const TimeDiff kMINUTES;      //!< The number of microseconds in a minute.
	static const TimeDiff kHOURS;       //!< The number of microseconds in a hour.
	static const TimeDiff kDAYS;        //!< The number of microseconds in a day.   

private:
	TimeDiff _span;
};



inline int Timespan::days() const
{
	return int(_span/kDAYS);
}


inline int Timespan::hours() const
{
	return int((_span/kHOURS) % 24);
}

	
inline int Timespan::totalHours() const
{
	return int(_span/kHOURS);
}

	
inline int Timespan::minutes() const
{
	return int((_span/kMINUTES) % 60);
}

	
inline int Timespan::totalMinutes() const
{
	return int(_span/kMINUTES);
}

	
inline int Timespan::seconds() const
{
	return int((_span/kSECONDS) % 60);
}

	
inline int Timespan::totalSeconds() const
{
	return int(_span/kSECONDS);
}

	
inline int Timespan::milliseconds() const
{
	return int((_span/kMILLISECONDS) % 1000);
}

	
inline Timespan::TimeDiff Timespan::totalMilliseconds() const
{
	return _span/kMILLISECONDS;
}

	
inline int Timespan::microseconds() const
{
	return int(_span % 1000);
}


inline int Timespan::useconds() const
{
	return int(_span % 1000000);
}

	
inline Timespan::TimeDiff Timespan::totalMicroseconds() const
{
	return _span;
}


inline bool Timespan::operator == (const Timespan& ts) const
{
	return _span == ts._span;
}


inline bool Timespan::operator != (const Timespan& ts) const
{
	return _span != ts._span;
}


inline bool Timespan::operator >  (const Timespan& ts) const
{
	return _span > ts._span;
}


inline bool Timespan::operator >= (const Timespan& ts) const
{
	return _span >= ts._span;
}


inline bool Timespan::operator <  (const Timespan& ts) const
{
	return _span < ts._span;
}


inline bool Timespan::operator <= (const Timespan& ts) const
{
	return _span <= ts._span;
}


inline bool Timespan::operator == (TimeDiff microSeconds) const
{
	return _span == microSeconds;
}


inline bool Timespan::operator != (TimeDiff microSeconds) const
{
	return _span != microSeconds;
}


inline bool Timespan::operator >  (TimeDiff microSeconds) const
{
	return _span > microSeconds;
}


inline bool Timespan::operator >= (TimeDiff microSeconds) const
{
	return _span >= microSeconds;
}


inline bool Timespan::operator <  (TimeDiff microSeconds) const
{
	return _span < microSeconds;
}


inline bool Timespan::operator <= (TimeDiff microSeconds) const
{
	return _span <= microSeconds;
}


inline void swap(Timespan& s1, Timespan& s2)
{
	s1.swap(s2);
}


} 

#endif 